﻿// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

#include "StateMachine.h"
#include "State.h"
#include "Action.h" 

using namespace std;
int main()
{
    std::cout << "Hello World!\n";
    int Exit = 0; // 退出。 
    int Continue = 1; // 继续执行。  

    StateMachine<int> sm;

    State<int>* yellowToRedState = new State<int>;  // （转红灯的）黄灯状态。
    State<int>* greenState = new State<int>;  // 绿灯状态。
    State<int>* yellowToGreenState = new State<int>;  // （转绿灯的）黄灯状态。
    State<int>* redState = new State<int>;  // 红灯状态。
    State<int>* initState = new State<int>;  // 初始状态。
    State<int>* finalState = new State<int>;  // 关闭状态。

    auto finalExec = []() {cout << "终止程序！" << endl; };
    finalState->setExec(finalExec);

    // 黄灯（转为红灯过渡） 
    yellowToRedState->setEnter([]() {cout << "进入黄灯状态。" << endl; });
    yellowToRedState->setExec([]() {cout << "Yellow (To Red ) Light Exec" << endl; });
    yellowToRedState->setExit([]() {cout << "退出黄灯状态。" << endl; });
    yellowToRedState->addTransition(Continue, redState); //黄灯关闭，转为红灯。
    yellowToRedState->addTransition(Exit, finalState); // 直接关闭，转为终止。

    // 绿灯。 
    greenState->setEnter([]() { cout << "进入绿灯状态" << endl; });
    greenState->setExec([]() { cout << "Green Light Exec" << endl; });
    greenState->setExit([]() { cout << "退出绿灯状态" << endl; });
    greenState->addTransition(Continue, yellowToRedState);
    greenState->addTransition(Exit, finalState); // 直接关闭，转为终止。

    // 黄灯（转为绿灯过渡） 
    yellowToGreenState->setEnter([]() { cout << "进入黄灯状态" << endl; });
    yellowToGreenState->setExec([]() { cout << "Yellow (ToGreen ) Light Exec" << endl; });
    yellowToGreenState->setExit([]() { cout << "退出黄灯状态" << endl; });
    yellowToGreenState->addTransition(Continue, greenState); //黄灯关闭，转为绿灯。
    yellowToGreenState->addTransition(Exit, finalState); // 直接关闭，转为终止。

    // 红灯。 
    redState->setEnter([]() { cout << "进入红灯状态" << endl; });
    redState->setExec([]() { cout << "Red Light Exec" << endl; });
    redState->setExit([]() { cout << "退出红灯状态" << endl; });
    redState->addTransition(Continue, yellowToGreenState); // 红灯关闭，黄灯打开。
    redState->addTransition(Exit, finalState); // 直接关闭，转为终止。
     
    initState->setExec([]() { cout << "InitState Exec" << endl; });
    initState->addTransition(Continue, redState); // 初始后，切换为红灯。
    initState->addTransition(Exit, finalState); // 直接关闭，转为终止。
     
    sm.addState(yellowToRedState);
    sm.addState(greenState);
    sm.addState(yellowToGreenState);
    sm.addState(redState);
    sm.addState(finalState);
    sm.addState(initState);

    sm.initState(initState); 

    if (sm.start())
    {
        std::cout << "启动完毕。" << endl;
        // 切换到下一个。
        sm.doAction(Action<int>(Continue)); 
        sm.doAction(Action<int>(Continue)); 
        sm.doAction(Action<int>(Continue));
        sm.doAction(Action<int>(Continue));
        sm.doAction(Action<int>(Continue));
        sm.doAction(Action<int>(Continue));
        sm.doAction(Action<int>(Continue));
        sm.doAction(Action<int>(Continue));
        sm.doAction(Action<int>(Continue));
        sm.doAction(Action<int>(Continue));
        // 切换到终止。
        sm.doAction(Action<int>(Exit));
    }
    else
    {
        std::cout << " 启动状态机失败。";
    }
    return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
